package redis2

import (
	"context"
	"gitee.com/chejiangyi/bsfgo/core/utils"
	"github.com/redis/go-redis/v9"
	"time"
)

type RedisOptions struct {
	Addr        string
	Db          int
	Username    string
	Password    string
	PoolSize    int
	MinPoolSize int
	MaxPoolSize int
}

type RedisClient struct {
	Client  *redis.Client
	context context.Context
}

func throwError(err error, operator string) {
	utils.LogUtil.Error(err, "redis %v操作失败", operator)
}

// Close 关闭 Redis 连接
func (r *RedisClient) Close() {
	throwError(r.Client.Close(), "Close")
}

// ==================== 基本 Key 操作 ====================

// Set 设置键值对，带过期时间
func (r *RedisClient) Set(key string, value interface{}, expiration time.Duration) {
	throwError(r.Client.Set(r.context, key, value, expiration).Err(), "Set")
}

// Get 获取键值
func (r *RedisClient) Get(key string) string {
	val, err := r.Client.Get(r.context, key).Result()
	throwError(err, "Get")
	return val
}

// GetBytes 获取键值，返回字节数组
func (r *RedisClient) GetBytes(key string) []byte {
	val, err := r.Client.Get(r.context, key).Bytes()
	throwError(err, "GetBytes")
	return val
}

// Exists 检查键是否存在
func (r *RedisClient) Exists(key string) bool {
	result, err := r.Client.Exists(r.context, key).Result()
	throwError(err, "Exists")
	return result == 1
}

// Delete 删除键
func (r *RedisClient) Delete(key string) {
	throwError(r.Client.Del(r.context, key).Err(), "Delete")
}

// Expire 设置键的过期时间
func (r *RedisClient) Expire(key string, expiration time.Duration) {
	throwError(r.Client.Expire(r.context, key, expiration).Err(), "Expire")
}

// TTL 获取键的剩余生存时间
func (r *RedisClient) TTL(key string) time.Duration {
	result, err := r.Client.TTL(r.context, key).Result()
	throwError(err, "TTL")
	return result
}

// ==================== 原子操作 ====================

// Incr 自增
func (r *RedisClient) Incr(key string) int64 {
	result, err := r.Client.Incr(r.context, key).Result()
	throwError(err, "Incr")
	return result
}

// Decr 自减
func (r *RedisClient) Decr(key string) int64 {
	result, err := r.Client.Decr(r.context, key).Result()
	throwError(err, "Decr")
	return result
}

// IncrBy 按指定步长自增
func (r *RedisClient) IncrBy(key string, value int64) int64 {
	result, err := r.Client.IncrBy(r.context, key, value).Result()
	throwError(err, "IncrBy")
	return result
}

// DecrBy 按指定步长自减
func (r *RedisClient) DecrBy(key string, value int64) int64 {
	result, err := r.Client.DecrBy(r.context, key, value).Result()
	throwError(err, "DecrBy")
	return result
}

// ==================== Hash 操作 ====================

// HSet 设置哈希字段值
func (r *RedisClient) HSet(key string, field string, value interface{}) {
	throwError(r.Client.HSet(r.context, key, field, value).Err(), "HSet")
}

// HGet 获取哈希字段值
func (r *RedisClient) HGet(key string, field string) string {
	result, err := r.Client.HGet(r.context, key, field).Result()
	throwError(err, "HGet")
	return result
}

// HGetAll 获取哈希所有字段和值
func (r *RedisClient) HGetAll(key string) map[string]string {
	result, err := r.Client.HGetAll(r.context, key).Result()
	throwError(err, "HGetAll")
	return result
}

// HDel 删除哈希字段
func (r *RedisClient) HDel(key string, fields ...string) {
	throwError(r.Client.HDel(r.context, key, fields...).Err(), "HDel")
}

// ==================== List 操作 ====================

// LPush 从列表左侧插入元素
func (r *RedisClient) LPush(key string, values ...interface{}) {
	throwError(r.Client.LPush(r.context, key, values...).Err(), "LPush")
}

// RPush 从列表右侧插入元素
func (r *RedisClient) RPush(key string, values ...interface{}) {
	throwError(r.Client.RPush(r.context, key, values...).Err(), "RPush")
}

// LPop 从列表左侧弹出元素
func (r *RedisClient) LPop(key string) string {
	result, err := r.Client.LPop(r.context, key).Result()
	throwError(err, "LPop")
	return result
}

// RPop 从列表右侧弹出元素
func (r *RedisClient) RPop(key string) string {
	result, err := r.Client.RPop(r.context, key).Result()
	throwError(err, "RPop")
	return result
}

// LRange 获取列表范围内的元素
func (r *RedisClient) LRange(key string, start, stop int64) []string {
	result, err := r.Client.LRange(r.context, key, start, stop).Result()
	throwError(err, "LRange")
	return result
}

// ==================== Set 操作 ====================

// SAdd 向集合添加元素
func (r *RedisClient) SAdd(key string, members ...interface{}) {
	throwError(r.Client.SAdd(r.context, key, members...).Err(), "SAdd")
}

// SMembers 获取集合所有元素
func (r *RedisClient) SMembers(key string) []string {
	result, err := r.Client.SMembers(r.context, key).Result()
	throwError(err, "SMembers")
	return result
}

// SIsMember 判断元素是否是集合成员
func (r *RedisClient) SIsMember(key string, member interface{}) bool {
	result, err := r.Client.SIsMember(r.context, key, member).Result()
	throwError(err, "SIsMember")
	return result
}

// SRem 从集合移除元素
func (r *RedisClient) SRem(key string, members ...interface{}) {
	throwError(r.Client.SRem(r.context, key, members...).Err(), "SRem")
}

// ==================== 高级功能 ====================

// SetJSON 将对象序列化为 JSON 并存储
func (r *RedisClient) SetJSON(key string, value interface{}, expiration time.Duration) {
	r.Set(key, utils.JsonUtil.ToJson(value), expiration)
}

// GetJSON 获取 JSON 数据并反序列化为对象
func (r *RedisClient) GetJSON(key string, data any) interface{} {
	jsonData := r.GetBytes(key)
	return utils.JsonUtil.FromJsonWithBytes(jsonData, data)
}

// GetJSON 获取 JSON 数据并反序列化为对象
func (r *RedisClient) SetNX(key string, value interface{}, expiration time.Duration) bool {
	result, err := r.Client.SetNX(r.context, key, value, expiration).Result()
	throwError(err, "SetNX")
	return result
}

// Lock 获取分布式锁
func (r *RedisClient) Lock(key string, value interface{}, expiration time.Duration) bool {
	return r.SetNX(key, value, expiration)
}

// Unlock 释放分布式锁
func (r *RedisClient) Unlock(key string) {
	r.Delete(key)
}

// Pipeline 执行管道操作
func (r *RedisClient) Pipeline(exec func(pipe redis.Pipeliner) error) {
	_, err := r.Client.Pipelined(r.context, exec)
	throwError(err, "Pipeline")
}

// ==================== 发布订阅 ====================

// Publish 发布消息到频道
func (r *RedisClient) Publish(channel string, message interface{}) int64 {
	result, err := r.Client.Publish(r.context, channel, message).Result()
	throwError(err, "Publish")
	return result
}

// Subscribe 订阅频道
func (r *RedisClient) Subscribe(channels ...string) *redis.PubSub {
	return r.Client.Subscribe(r.context, channels...)
}

// ==================== 其他 ====================

// Keys 查找匹配模式的键
func (r *RedisClient) Keys(pattern string) []string {
	result, err := r.Client.Keys(r.context, pattern).Result()
	throwError(err, "Keys")
	return result
}

// FlushDB 清空当前数据库
func (r *RedisClient) FlushDB() {
	throwError(r.Client.FlushDB(r.context).Err(), "FlushDB")
}

// FlushAll 清空所有数据库
func (r *RedisClient) FlushAll() {
	throwError(r.Client.FlushAll(r.context).Err(), "FlushAll")
}
